# -*- coding: utf-8 -*-
"""
Stream
"""

import base64
import logging
import cElementTree as etree
import PyLucene

#import zope.interface

#from interfaces import IXMLQuery
#from interfaces import IXMLSearchQuery

logger = logging.getLogger("nokcene.xmlquery")

def fillFields (field, encoding="utf8") :

	id_ = field.attrib.get("id", "").strip()
	if not id_ :
		return None

	value = unicode()

	if field.text :
		# Deal with base64 if encoded
		#try :
		#	value = base64.b64decode(field.text)
		#except :
		#	value = field.text.strip()
		value = field.text.strip()

		## Convert to unicode.
		#try :
		#	value = unicode(value)
		#except UnicodeError :
		#	try :
		#		value = unicode(value, encoding)
		#	except UnicodeError :
		#		value = unicode(value, "utf8")

	if field.attrib.get("is_store", "").strip().lower() == "true" :
		__is_store = PyLucene.Field.Store.YES
	else :
		__is_store = PyLucene.Field.Store.NO

	if field.attrib.get("is_tokenized", "").strip().lower() == "true" :
		__is_tokenized = PyLucene.Field.Index.TOKENIZED
	else :
		__is_tokenized = PyLucene.Field.Index.UN_TOKENIZED

	return \
		{
			"id" : id_,
			"attribute" : field.attrib.get("attribute", "").strip(),
			"type" : field.attrib.get("type", "").strip(),
			"value": value,
			"analyzer" : field.attrib.get("analyzer", "cjk").strip(),
			"is_tokenized" : __is_tokenized,
			"is_store" : __is_store,
		}

class XMLQuery(object) :

	#zope.interface.implements(IXMLQuery)

	def __init__(self, xml_stream="", encoding="utf8") :
		"""
		<doc>
		  <fields>
			<field id="name" type="text" analyzer="cjk"
					is_tokenized="true" is_store="true">
			  The value of the field to index
			</field>
		  </fields>
		</doc>

		'type' is
			text
			multikeyword
			keyword
			date
			path
			sort
		"""

		self._xml_stream = xml_stream
		self._encoding = encoding
		self._fields = ()

		if not xml_stream :
			return

		try :
			doc = etree.XML(self._xml_stream)
		except :
			raise

		fields = doc.findall("fields/field")
		for field in fields :
			__data = fillFields(field)
			if not __data :
				continue

			self._fields += (__data, )

	def getFields(self) :
		return self._fields

	def getFieldNames(self) :
		return tuple([x["id"] for x in self._fields])

class XMLSearchQuery :

	#zope.interface.implements(IXMLSearchQuery)

	def __init__(self, xml_stream="") :

		self.xml_stream = xml_stream

		self._analyzer = "standard"

		self._return_fields = []
		self._search_fields = []
		self._search_options = {}

		self._operator = "AND"

		self._start = 0
		self._results = 10

		self.parse()

	def parse (self) :
		if not self.xml_stream :
			return

		#doc = etree.XML(xml_stream.encode("utf-8"))
		try :
			self.doc = etree.XML(self.xml_stream.encode("utf-8"))
		except Exception, e :
			print e
			raise

		self.parseAnalyzerType()
		self.parseReturnFields()
		self.parseFields()
		self.parseEtc()

	def parseAnalyzerType (self) :
		analyzers = self.doc.findall("analyzer")
		if analyzers :
			self._analyzer = unicode(analyzers[0].text.strip())

	def parseReturnFields (self) :
		return_fields = self.doc.findall("return_fields/field")
		for return_field in return_fields :
			if return_field.text :
				self._return_fields.append(unicode(return_field.text.strip()))

	def parseFields (self) :
		fields = self.doc.findall("fields/field")
		for field in fields :
			if field.attrib.get("id") and field.attrib.get("value") :
				mapping = {
					"id" : unicode(field.attrib["id"].strip()),
					"value" : unicode(field.attrib["value"].strip()),
					"type" : unicode(field.attrib.get("type", "").strip()),
					"analyzer" : unicode(field.attrib.get("analyzer",
														  "standard")).strip(),
					}

				if field.attrib.get("usage") is not None :
					mapping["usage"] = unicode(field.attrib["usage"]).strip()

				condition = field.attrib.get("condition")
				if condition is not None :
					mapping["condition"] = unicode(condition.strip())

				usage = field.attrib.get("usage")
				if usage is not None :
					mapping["usage"] = usage.strip()
				self._search_fields.append(mapping)

	def parseEtc (self) :
		batch = self.doc.find("batch")
		if batch is not None :
			for attr in ("start", "size") :
				self._search_options[attr] = batch.attrib.get(attr)

		sort = self.doc.find("sort")
		if sort is not None :
			for tagname in ("sort-on", "sort-limit", "sort-order") :
				elt = sort.find(tagname)
				if elt is not None :
					self._search_options[tagname] = elt.text

		elt = self.doc.find("operator")
		if elt is not None :
			self._search_options["operator"] = elt.text

	def getReturnFields(self) :
		return tuple(self._return_fields)

	def getSearchFields(self) :
		# Add path field type at the end

		_fields = []
		_ends = []
		for each in self._search_fields :
			if each["type"].lower() == "path" :
				_ends.append(each)
			else :
				_fields.append(each)

		for each in _ends :
			_fields.append(each)

		return tuple(_fields)

	def getSearchOptions(self) :
		return self._search_options

	def getAnalyzerType(self) :
		return self._analyzer

if __name__ == "__main__"  :
	a = \
"""<?xml version="1.0" encoding="utf-8" ?>
		<doc>
		  <fields>
			<field id="name" type="text" analyzer="French" is_tokenized="true" is_store="true">
			우리나라
			</field>
		  </fields>
		</doc>
"""
	__x = XMLQuery(unicode(a, "utf8").encode("utf8"))

	print __x.getFields()

